package javaNIO1.channel;

import javax.management.StandardEmitterMBean;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;

/**
 * Created with Intel IDEA.
 *  内存映射缓冲区
 * @Auther: gjt
 * @Date: 2024/7/14 16:45
 */
public class MappedBuffer {

    public static void main(String[] args) throws IOException {
        File testFile = File.createTempFile("mmaptest", null);
        RandomAccessFile file = new RandomAccessFile(testFile, "rw");
        FileChannel channel = file.getChannel();
        ByteBuffer tmpBuffer = ByteBuffer.allocate(100);
        tmpBuffer.put("This is the file content".getBytes());
        tmpBuffer.flip();
        channel.write(tmpBuffer,0);
        tmpBuffer.clear();
        tmpBuffer.put("This is more file content".getBytes());
        tmpBuffer.flip();
        channel.write(tmpBuffer, 8192);

        MappedByteBuffer ro = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());
        MappedByteBuffer rw = channel.map(FileChannel.MapMode.READ_WRITE, 0, channel.size());
        MappedByteBuffer cow = channel.map(FileChannel.MapMode.PRIVATE, 0, channel.size());

        System.out.println("Begin");
        showBuffers(ro, rw, cow);
        cow.position(8);
        cow.put("COW".getBytes());
        System.out.println("Change to COW buffer");
        showBuffers(ro, rw, cow);

        rw.position(9);
        rw.put("R/W".getBytes());
        rw.position(8194);
        rw.put("R/W".getBytes());
        rw.force();
        System.out.println("Change to R/W buffer");
        showBuffers(ro, rw, cow);

        tmpBuffer.clear();
        tmpBuffer.put("Channel write".getBytes());
        channel.write(tmpBuffer, 0);
        tmpBuffer.rewind();
        channel.write(tmpBuffer, 8202);
        System.out.println("Write on Channel");
        showBuffers(ro, rw, cow);

        cow.position(8207);
        cow.put("COW2".getBytes());
        System.out.println("Second Change to COW buffer");
        showBuffers(ro, rw, cow);

        rw.position(0);
        rw.put("R/W2".getBytes());
        rw.position(8210);
        rw.put("R/W2".getBytes());
        rw.force();
        System.out.println("Second Change to R/W buffer");
        showBuffers(ro, rw, cow);

        channel.close();
        file.close();
        testFile.delete();
    }


    private static void showBuffers (ByteBuffer ro ,ByteBuffer rw, ByteBuffer cow){
        dumpBuffer("R/O", ro);
        dumpBuffer("R/W", rw);
        dumpBuffer("COW", cow);
        System.out.println("");
    }

    private static void dumpBuffer(String prefix, ByteBuffer buffer){
        System.out.print(prefix + ": '");
        int nulls = 0;
        int limit = buffer.limit();
        for (int i = 0; i < limit; i++) {
            char c = (char) buffer.get(i);

            // 字节数据中的空值
            if(c == '\u0000'){
                nulls++;
                continue;
            }

            if(nulls != 0){
                System.out.print("|[" + nulls + " nulls]|");
                nulls = 0;
            }
            System.out.print(c);
        }
        System.out.println("'");
    }
}
